package com.zhanghaijun.createCode.ad.util;



import com.enniu.commons.basic.Answer;
import com.zhanghaijun.createCode.ad.bean.AdUser;
import com.zhanghaijun.createCode.ad.bean.OuBean;
import com.zhanghaijun.createCode.ad.bean.SearchOuUserResultBean;
import com.zhanghaijun.createCode.ad.factory.AdConnectionFactory;
import com.zhanghaijun.createCode.security.HttpClientUtil;
import com.zhanghaijun.createCode.util.JsonResultDto;
import com.zhanghaijun.createCode.util.PropsUtils;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.*;
import javax.naming.ldap.InitialLdapContext;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by zhanghaijun on 15/6/10.
 */
public class AdDoActionUtil {


    private static String dcBase = PropsUtils.getProp("adDcBase");
    private static String adDCRootOu = PropsUtils.getProp("adDCRootOu");
    public static final String CHANGE_PWD_URL = PropsUtils.getProp("adChangePassWordUrl");
    public static final String charset = "gbk";

    /**
     * 添加AdUser
     * 存在 则不添加
     *
     * @param adUser
     * @return JsonResultDto
     */
    public static JsonResultDto add(AdUser adUser) {
        try {
            DirContext ds = AdConnectionFactory.getDirContextInstance();
            String loginName = adUser.getLoginName();
            SearchOuUserResultBean searchOuUserResultBean = searchOuUserByUserPrincipalName(loginName);
            if (searchOuUserResultBean != null) {
                return new JsonResultDto(false, 101, "adUser is already exist");
            }
            Attributes attrs = new BasicAttributes();
            attrs.put("displayName", adUser.getDisplayName());
            attrs.put("uid", adUser.getUid());
            attrs.put("sn", adUser.getSn());
            attrs.put("cn", adUser.getCn());
            attrs.put("mail", adUser.getMail());
            if (adUser.getStreetAddress() != null) {
                attrs.put("streetAddress", adUser.getStreetAddress());
            }
            attrs.put("sAMAccountName", adUser.getsAMAccountName());
            attrs.put("employeeId", adUser.getEmployeeId());
            attrs.put("userPassword", "12345@abc".getBytes());
            String principalNameSuffix = PropsUtils.getProp("principalNameSuffix");
            attrs.put("userPrincipalName", adUser.getLoginName() + principalNameSuffix);
            attrs.put("userAccountControl", "544");
            attrs.put("pwdLastSet", "-1");

            String newPassword="a123456";
            String newQuotedPassword = "\"" + newPassword + "\"";
            byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
            attrs.put("unicodePwd",newUnicodePassword);

            Attribute objclass = new BasicAttribute("objectClass");
            String[] attrObjectClassPerson = {"inetOrgPerson", "organizationalPerson", "person", "top", "user"};
            Arrays.sort(attrObjectClassPerson);
            for (String ocp : attrObjectClassPerson) {
                objclass.add(ocp);
            }
            attrs.put(objclass);
            ds.createSubcontext(adUser.getSubContext(), attrs);
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResultDto(false, 102, "some error occur in save adUser");
        }
        return new JsonResultDto(true);
    }


    /**
     * 添加ou
     *
     * @param ouBean
     * @return
     */
    public static JsonResultDto addOu(OuBean ouBean) {
        try {
            DirContext ds = AdConnectionFactory.getDirContextInstance();
            Attributes attrs = new BasicAttributes();
            attrs.put("displayName", ouBean.getDescription());
            Attribute objclass = new BasicAttribute("objectClass");
            objclass.add("organizationalUnit");
            objclass.add("top");
            attrs.put(objclass);
            attrs.put("objectCategory",PropsUtils.getProp("objectCategory"));
            attrs.put("ou", ouBean.getOu());
            attrs.put("description", ouBean.getDescription());
            ds.createSubcontext(ouBean.getSubContext(), attrs);
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResultDto(false);
        }

        return new JsonResultDto(true);
    }

    /**
     * 通过userPrincipalName 查找AD用户
     *
     * @param loginName
     * @return
     */
    public static SearchOuUserResultBean searchOuUserByUserPrincipalName(String loginName) {
        SearchOuUserResultBean searchOuUserResultBean = null;
        String principalNameSuffix = PropsUtils.getProp("principalNameSuffix");
        String userPrincipalName = loginName + principalNameSuffix;
        try {
            DirContext ds = AdConnectionFactory.getDirContextInstance();
            SearchControls searchCtls = new SearchControls();
            searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            String searchFilter = "(&(objectClass=user)(userPrincipalName=" + userPrincipalName + "))";
            String searchBase = dcBase;
            String returnedAtts[] = {"displayName", "distinguishedName"};
            searchCtls.setReturningAttributes(returnedAtts);
            NamingEnumeration<SearchResult> entries = ds.search(searchBase,
                    searchFilter, searchCtls);
            if (entries.hasMoreElements()) {
                SearchResult entry = entries.next();
                Attributes attrs = entry.getAttributes();
                searchOuUserResultBean = new SearchOuUserResultBean();
                if (attrs != null) {
                    for (NamingEnumeration<? extends Attribute> names = attrs
                            .getAll(); names.hasMore(); ) {
                        Attribute attr = names.next();
                        String attrId = attr.getID();
                        for (NamingEnumeration<?> e = attr.getAll(); e.hasMore(); ) {
                            if ("displayName".equals(attrId)) {
                                searchOuUserResultBean.setDisplayName(String.valueOf(e.next()));
                            }

                            if ("distinguishedName".equals(attrId)) {
                                searchOuUserResultBean.setDistinguishedName(String.valueOf(e.next()));
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return searchOuUserResultBean;
    }

    /**
     * 更新distinguishedName
     *
     * @return
     */
    public static JsonResultDto reNameDistinguishedName(String oldName, String newName) {
        DirContext ds = AdConnectionFactory.getDirContextInstance();
        try {
            ds.rename(oldName, newName);
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResultDto(false, 101, "some error occur in reNameDistinguishedName");
        }
        return new JsonResultDto(true);
    }

    /**
     * 根据distinguishedName 判断组织或者个人是否存在
     *
     * @param distinguishedName
     * @return
     */
    public static boolean searchByDistinguishedName(String distinguishedName) {
        try {
            DirContext ds = AdConnectionFactory.getDirContextInstance();
            SearchControls searchCtls = new SearchControls();
            searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            String searchFilter = "(&(distinguishedName=" + distinguishedName + "))";
            String searchBase = dcBase;
            String returnedAtts[] = {"displayName", "name"};
            searchCtls.setReturningAttributes(returnedAtts);
            NamingEnumeration<SearchResult> entries = ds.search(searchBase,
                    searchFilter, searchCtls);
            if (entries.hasMoreElements()) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static void searchAllUser(){
        try{
            DirContext ds = AdConnectionFactory.getDirContextInstance();
            SearchControls searchCtls = new SearchControls();
            searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            String searchFilter = "objectClass=User";
            String searchBase = dcBase;
            String returnedAtts[] = {"sn","mail","sAMAccountName"};
            searchCtls.setReturningAttributes(returnedAtts);
            NamingEnumeration<SearchResult> entries = ds.search(searchBase,
                    searchFilter, searchCtls);
            while (entries.hasMoreElements()) {
                SearchResult sr = (SearchResult) entries.next();
                Attributes Attrs = sr.getAttributes();// 得到符合条件的属性集
                for (NamingEnumeration ne = Attrs.getAll(); ne.hasMore();) {
                    Attribute Attr = (Attribute) ne.next();// 得到下一个属性
                    //System.out.println(" AttributeID=属性名："+ Attr.getID().toString());
                    // 读取属性值
                    for (NamingEnumeration e = Attr.getAll(); e.hasMore();) {
                        String value =  e.next().toString();
                        System.out.println("AttributeValues=属性值：" + value);
//                        String mail = value + "@u51.com";
//                        System.out.println(mail);
//                        Map<String,Object> params = new HashMap<String,Object>();
//                        params.put("mail",mail);
//                        update(value,params);
                       // System.out.println("AttributeValues=属性值：" + value);
                    }
                    //System.out.println("    ---------------");

                }
            }

        }catch (Exception e){
          e.printStackTrace();
        }



    }




    /**
     * create根OU
     * 存在 则不创建
     */
    public static void createRootOu() {
        StringBuffer sb = new StringBuffer();
        sb.append("ou=").append("U51").append(",");
        sb.append(dcBase);
        String rootDistinguishedName = sb.toString();
        boolean rootIsExist = searchByDistinguishedName(rootDistinguishedName);
        if (!rootIsExist) {
            OuBean ouBean = new OuBean();
            ouBean.setDescription("U51");
            ouBean.setDisplayName("U51");
            ouBean.setOu("U51");
            ouBean.setSubContext(rootDistinguishedName);
            addOu(ouBean);
        }
    }

    /**
     * 更新AD用户属性
     *
     * @param longName
     * @param params
     */
    public static JsonResultDto update(String longName, Map<String, Object> params) {
        try {
            DirContext ds = AdConnectionFactory.getDirContextInstance();
            SearchOuUserResultBean searchOuUserResultBean = searchOuUserByUserPrincipalName(longName);
            if (searchOuUserResultBean != null) {
                Set<String> set = params.keySet();
                ModificationItem[] mods = new ModificationItem[set.size()];
                int index = 0;
                for (String key : set) {
                    Attribute attr = new BasicAttribute(key, params.get(key));
                    mods[index] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr);
                }
                ds.modifyAttributes(searchOuUserResultBean.getDistinguishedName(), mods);
            } else {
                return new JsonResultDto(false, 101, "ADUser has not exist");
            }
        } catch (Exception e) {
            return new JsonResultDto(false, 101, "some error occur in update ADUSER");
        }
        return new JsonResultDto(true);
    }


    /**
     * 修改AD密码
     * @param acct 账号
     * @param oldPwd 旧密码
     * @param newPwd 新密码
     */
    public static JsonResultDto changePassword(String acct,String oldPwd,String newPwd){
        Answer<String> rt = new Answer<String>();
        rt.setCode(500);
        String httpOrgCreateTest = CHANGE_PWD_URL ;
        Map<String,String> createMap = new HashMap<String,String>();
        createMap.put("acct",acct);
        createMap.put("old",oldPwd);
        createMap.put("new",newPwd);
        createMap.put("new2",newPwd);

        try {
            String rtStr = new HttpClientUtil().doPost(httpOrgCreateTest, createMap, charset);

            int successFlag = rtStr.indexOf("密码成功更改");
            if(successFlag>=0){
                return new JsonResultDto(true,101,"修改成功");
            }else{
                String regex="<p>(.*?)<br>";
                Pattern p =Pattern.compile(regex);
                Matcher m=p.matcher(rtStr);
                String res ="";
                while(m.find()){
                    res =m.group(1);
                }
                if("".equals(res.trim())){
                    return new JsonResultDto(false,101,"修改失败");
                }else{
                    return new JsonResultDto(false,101,res);
                }
            }

        }catch(Exception e){
            rt.setMsg(e.getMessage());
        }
        return new JsonResultDto(false,101,"修改出错");
    }

    /**
     * 认证
     * @param loginName
     * @param pwd
     * @return
     */
    public static boolean authenticateUserNameAndPwd(String loginName,String pwd){
        DirContext ds = null;
        String providerUrl = PropsUtils.getProp("adServerHost389");
        Hashtable ldapEnv = new Hashtable();
        ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        ldapEnv.put(Context.PROVIDER_URL,providerUrl);
        ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
        ldapEnv.put(Context.SECURITY_PRINCIPAL,loginName+PropsUtils.getProp("principalNameSuffix"));
        ldapEnv.put(Context.SECURITY_CREDENTIALS, pwd); // 密码
        try{
            ds = new InitialLdapContext(ldapEnv, null);
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {ds.close();}catch (Exception e){e.printStackTrace();}
        }
        return false;
    }



    public static String createOUDistinguishedName(String[] ouNames) {
        int length = ouNames.length;
        String[] reverseArr = new String[length];
        for(int i=0;i<length;i++){
            reverseArr[length-i-1] = ouNames[i];
        }

        StringBuffer sb = new StringBuffer();
        for (String ouName : reverseArr) {
            if(ouName!=null){
                sb.append("ou=").append(ouName).append(",");
            }
        }
        sb.append(adDCRootOu);
        return sb.toString();
    }


    public static String createCnDistinguishedName(String[] ouNames, String personCN) {
        int length = ouNames.length;
        String[] reverseArr = new String[length];
        for(int i=0;i<length;i++){
            reverseArr[length-i-1] = ouNames[i];
        }
        StringBuffer sb = new StringBuffer();
        if (personCN != null) {
            sb.append("cn=").append(personCN).append(",");
        }
        for (String ouName : reverseArr) {
            if(ouName!=null){
                sb.append("ou=").append(ouName).append(",");
            }
        }
        sb.append(adDCRootOu);
        return sb.toString();
    }

    public static void main(String[] args) {
//        SearchOuUserResultBean searchOuUserResultBean = searchOuUserByUserPrincipalName("qianchengzhang");
//        System.out.println(searchOuUserResultBean.getDisplayName());
        //PrintUtil.println(searchOuUserResultBean.getDisplayName());
        //PrintUtil.println(searchByDistinguishedName("CN=施春艳,OU=产品组,OU=金融事业部,OU=哥牛,OU=U51,DC=51,DC=nb"));
//        JsonResultDto res =reNameDistinguishedName("CN=施春艳,OU=51人品事业部,OU=恩牛网络,OU=U51,DC=51,DC=nb","CN=施春艳,OU=产品组,OU=金融事业部,OU=哥牛,OU=U51,DC=51,DC=nb");
//        PrintUtil.println(res.isSuccess());
//          Map<String,Object> params = new HashMap<String,Object>();
//          params.put("mail","296876809@qq.com");
//          JsonResultDto res = update("zhanghaijun",params);
//          PrintUtil.println(res.isSuccess());

        searchAllUser();
//        Map<String,Object> params = new HashMap<String,Object>();
//        params.put("mail","jiyaqing@u51.com");
//        update("jiyaqing",params);

        //searchOuUserByUserPrincipalName("jiyaqing");
    }
}
